import os
import shutil
from workload.workloads_manager import WorkloadManager
from common.benchmark_var import GlobalEnv
from utils.executor import Executor
from utils.utils import Utils
from framework.native_workload import NativeWorkload
from common.benchmark_var import MeasureUnit


class HwcodecWorkload(NativeWorkload):
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = 'hwcodec'
        self.use_makefile = True
        self.lang = 'C'
        self.description = ''
        self.desc = ''
        self.TMPDIR = os.path.join(self.src_dir, 'source')
        self.exe = "videodecode.sh"
        self.program_options = ""
        self.support_multi_instance = False
        self.valid = True

    def makefile_build(self):
        self._copy_src2build()
        make_res = self._make()
        return make_res

    def _make(self):
        executor = Executor(desc='make_hwcodec',
                        command='make -j',
                        exec_dir=self.build_dir,
                        debug=self.debug)
        res = executor.exec()
        if res == 0:
            self._copy_exe2bin()
            return True
        else:
            return False

    def _copy_src2build(self):
        files = os.listdir(self.src_dir)
        for file in files:
            src_file = os.path.join(self.src_dir, file)
            dst_file = os.path.join(self.build_dir, file)
            if os.path.exists(dst_file):
                shutil.rmtree(dst_file) if os.path.isdir(dst_file) else os.remove(dst_file)
            if os.path.isdir(src_file):
                shutil.copytree(src_file, dst_file)
            else:
                shutil.copy(src_file, self.build_dir)

    def _copy_exe2bin(self):
        exe = os.path.join(self.build_dir, 'exec', "videodecode")
        sh = os.path.join(self.build_dir, "videodecode.sh")
        conf = os.path.join(self.build_dir, 'exec', "vendorconfig.ini")
        Utils.copy_file(exe, self.bin_dir)
        Utils.copy_file(sh, self.bin_dir)
        Utils.copy_file(conf, self.bin_dir)

    def get_instance_cmd(self, instance):
        executors = []
        cmd = "{}/{} {}".format(self.bin_dir, self.exe, self.program_options)
        executor = Executor(desc=self.desc,
                            command=cmd,
                            debug=self.debug,
                            exec_dir=instance.instance_dir)
        executors.append(executor)

        return executors

    def get_raw_score(self, instance):
        result_file = os.path.join(instance.instance_dir, self.desc + ".log")   #see Executor.__init__()
        if not os.path.exists(result_file):
            return 0
        with open(result_file, 'r') as f:
            lines = f.readlines()
            for i in range(len(lines)):
                score_line = lines[i].strip()
                if score_line.find('|') != -1:
                    str_list = score_line.split('|')
                    score = float(str_list[1])
                    return score
        return 0

    def setup_dir(self):
        self.work_dir = os.path.join(GlobalEnv.GCBS_WORKLOAD_DIR, "hwcodec")
        self.src_dir = os.path.join(self.work_dir, 'src')
        self.build_dir = os.path.join(self.work_dir, 'build')
        self.data_dir = os.path.join(self.work_dir, 'data')
        self.log_dir = os.path.join(self.work_dir, 'log')
        self.bin_dir = os.path.join(self.work_dir, 'bin')
        self.run_dir = os.path.join(self.work_dir, 'run', self.name)

        dir_list = [self.work_dir, self.src_dir, self.build_dir, self.data_dir,
                    self.log_dir, self.run_dir, self.bin_dir]
        for directory in dir_list:
            if not os.path.exists(directory):
                os.makedirs(directory)


@WorkloadManager.register_workload('dec_vaapi_x11_264')
class Decvaapix11264Workload(HwcodecWorkload):
    DESC = "vaapi: dec-x11"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vaapi_x11_264"
        self.description = Decvaapix11264Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vaapi -c %s"%(os.path.join(self.data_dir, "H264_3840X2160_100Mbps_29.97fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vaapi_x11_264"


@WorkloadManager.register_workload('dec_vaapi_x11_265')
class Decvaapix11265Workload(HwcodecWorkload):
    DESC = "vaapi: dec-x11"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vaapi_x11_265"
        self.description = Decvaapix11265Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vaapi -c %s"%(os.path.join(self.data_dir, "HEVC_3840x2160_10Mbps_59.94fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vaapi_x11_265"


@WorkloadManager.register_workload('dec_vaapi_drm_264')
class Decvaapidrm264Workload(HwcodecWorkload):
    DESC = "vaapi: dec-drm"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vaapi_drm_264"
        self.description = Decvaapidrm264Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vaapi -d -c %s"%(os.path.join(self.data_dir, "H264_3840X2160_100Mbps_29.97fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vaapi_drm_264"


@WorkloadManager.register_workload('dec_vaapi_drm_265')
class Decvaapidrm265Workload(HwcodecWorkload):
    DESC = "vaapi: dec-drm"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vaapi_drm_265"
        self.description = Decvaapidrm265Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vaapi -d -c %s"%(os.path.join(self.data_dir, "HEVC_3840x2160_10Mbps_59.94fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vaapi_drm_265"


@WorkloadManager.register_workload('dec_vdpau_x11_264')
class Decvdpaux11264Workload(HwcodecWorkload):
    DESC = "vdpau: dec-x11"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vdpau_x11_264"
        self.description = Decvdpaux11264Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vdpau -c %s"%(os.path.join(self.data_dir, "H264_3840X2160_100Mbps_29.97fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vdpau_x11_264"


@WorkloadManager.register_workload('dec_vdpau_x11_265')
class Decvdpaux11265Workload(HwcodecWorkload):
    DESC = "vdpau: dec-x11"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vdpau_x11_265"
        self.description = Decvdpaux11265Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vdpau -c %s"%(os.path.join(self.data_dir, "HEVC_3840x2160_10Mbps_59.94fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vdpau_x11_265"


@WorkloadManager.register_workload('dec_vdpau_drm_264')
class Decvdpaudrm264Workload(HwcodecWorkload):
    DESC = "vdpau: dec-drm"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vdpau_drm_264"
        self.description = Decvdpaudrm264Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vdpau -d -c %s"%(os.path.join(self.data_dir, "H264_3840X2160_100Mbps_29.97fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vdpau_drm_264"


@WorkloadManager.register_workload('dec_vdpau_drm_265')
class Decvdpaudrm265Workload(HwcodecWorkload):
    DESC = "vdpau: dec-drm"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "dec_vdpau_drm_265"
        self.description = Decvdpaudrm265Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwdec -p vdpau -d -c %s"%(os.path.join(self.data_dir, "HEVC_3840x2160_10Mbps_59.94fps.mp4"))
        self.setup_dir()
        self.desc = "dec_vdpau_drm_265"


@WorkloadManager.register_workload('enc_vaapi_yuyv_264')
class Encvaapiyuyv264Workload(HwcodecWorkload):
    DESC = "vaapi: enc"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "enc_vaapi_yuyv_264"
        self.description = Encvaapiyuyv264Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwencode -c %s -f %s -s %s -o yuyv.h264 -n h264_vaapi"%(os.path.join(self.data_dir, "ParkScene_1920x1080_24_yuy2_1.yuv"), "yuyv", "1920x1080")
        self.setup_dir()
        self.desc = "enc_vaapi_yuyv_264"


@WorkloadManager.register_workload('enc_vaapi_i420_264')
class Encvaapii420264Workload(HwcodecWorkload):
    DESC = "vaapi: enc"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "enc_vaapi_i420_264"
        self.description = Encvaapii420264Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwencode -c %s -f %s -s %s -o i420.h264 -n h264_vaapi"%(os.path.join(self.data_dir, "ParkScene_1920x1080_24_i420_1.yuv"), "i420", "1920x1080")
        self.setup_dir()
        self.desc = "enc_vaapi_i420_264"


@WorkloadManager.register_workload('enc_vaapi_yuyv_265')
class Encvaapiyuyv265Workload(HwcodecWorkload):
    DESC = "vaapi: enc"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "enc_vaapi_yuyv_265"
        self.description = Encvaapiyuyv265Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwencode -c %s -f %s -s %s -o yuyv.hevc -n hevc_vaapi"%(os.path.join(self.data_dir, "ParkScene_1920x1080_24_yuy2_1.yuv"), "yuyv", "1920x1080")
        self.setup_dir()
        self.desc = "enc_vaapi_yuyv_265"

@WorkloadManager.register_workload('enc_vaapi_i420_265')
class Encvaapii420265Workload(HwcodecWorkload):
    DESC = "vaapi: enc"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "enc_vaapi_i420_265"
        self.description = Encvaapii420265Workload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.program_options = "-t hwencode -c %s -f %s -s %s -o i420.hevc -n hevc_vaapi"%(os.path.join(self.data_dir, "ParkScene_1920x1080_24_i420_1.yuv"), "i420", "1920x1080")
        self.setup_dir()
        self.desc = "enc_vaapi_i420_265"
